package com.telchina.common.aspect;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.telchina.common.annotation.DataScope;
import com.telchina.common.core.domain.BaseEntity;
import com.telchina.common.core.domain.entity.SysRole;
import com.telchina.common.core.domain.model.LoginUser;
import com.telchina.common.domain.WoDataPermission;
import com.telchina.common.mapper.WoDataPermissionMapper;
import com.telchina.common.utils.SecurityUtils;
import com.telchina.common.utils.StringUtils;
import com.telchina.workorder.third.service.SystemThirdService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Aspect
@Component
public class DataScopeAspect {
    /**
     * 全部数据权限
     */
    public static final String DATA_SCOPE_ALL = "1";

    /**
     * 部门数据权限
     */
    public static final String DATA_SCOPE_DEPT = "2";

    /**
     * 部门及以下数据权限
     */
    public static final String DATA_SCOPE_DEPT_AND_CHILD = "3";

    /**
     * 仅本人数据权限
     */
    public static final String DATA_SCOPE_SELF = "4";

    /**
     * 自定数据权限
     */
    public static final String DATA_SCOPE_CUSTOM = "5";

    /**
     * 数据权限过滤关键字
     */
    public static final String DATA_SCOPE = "dataScope";

    @Autowired
    private SystemThirdService systemThirdService;


    @Autowired
    private WoDataPermissionMapper dataPermissionMapper;


    @Before("@annotation(controllerDataScope)")    // 这个controllerDataScope是一个形参
    public void doBefore(JoinPoint point, DataScope controllerDataScope) throws Throwable {
        clearDataScope(point);
        handleDataScope(point, controllerDataScope);
    }

    protected void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope) {
        LoginUser currentUser = SecurityUtils.getLoginUser();

        // 如果是超级管理员，则不过滤数据
        if (!SecurityUtils.isAdmin(currentUser.getUserId())) {
            dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptColumnAlias(), controllerDataScope.useColumnAlias());
        }
    }

    /**
     * 数据范围过滤
     *
     * @param joinPoint       切点
     * @param user            用户
     * @param deptColumnAlias 部门别名
     * @param useColumnAlias  用户别名
     */
    public void dataScopeFilter(JoinPoint joinPoint, LoginUser user, String deptColumnAlias, String useColumnAlias) {

        List<SysRole> roles = user.getUser().getRoles();
        if (CollUtil.isEmpty(roles)) {
            throw new RuntimeException("未获取到用户角色信息！");
        }
        // 获取角色配置信息
        List<String> roleCodes = roles.stream().map(SysRole::getCode).collect(Collectors.toList());
        List<WoDataPermission> dataPermissionList = dataPermissionMapper.selectList(new QueryWrapper<WoDataPermission>()
                .lambda().in(WoDataPermission::getRoleId, roleCodes));
//        if (CollUtil.isEmpty(dataPermissionList)) {
//            throw new RuntimeException("未获取到角色权限配置信息！");
//        }

        StringBuilder sqlString = new StringBuilder();

        for (WoDataPermission dataPermission : dataPermissionList)   //获取当前用户的角色
        {
            String dataScope = dataPermission.getType();   //获取角色的数据权限

            // 若这个角色的数据权限是  全部数据权限
            if (DATA_SCOPE_ALL.equals(dataScope)) {
                sqlString = new StringBuilder();
                break;
            }

            //自定义数据权限
            else if (DATA_SCOPE_CUSTOM.equals(dataScope)) {
                String deptIds = Stream.of(dataPermission.getDeptId().split(",")).collect(Collectors.joining("','"));
                sqlString.append(StringUtils.format(
                        " OR {} IN () ", deptColumnAlias,
                        deptIds));
            }

            //本部门数据权限
            else if (DATA_SCOPE_DEPT.equals(dataScope)) {
                sqlString.append(StringUtils.format(" OR {} = '{}' ", deptColumnAlias, user.getUser().getOrg().getId()));
            }

            //本部门及以下数据权限
            else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) {
                List<String> deptIdLists = systemThirdService.getDeptIdByParentId(user.getUser().getOrg().getId());
                String deptIds = deptIdLists.stream().collect(Collectors.joining("','"));
                sqlString.append(StringUtils.format(
                        " OR {} IN ('{}') ", deptColumnAlias,
                        deptIds));
            }

            //仅本人数据权限
            else if (DATA_SCOPE_SELF.equals(dataScope)) {
                if (StringUtils.isNotBlank(useColumnAlias)) {
                    sqlString.append(StringUtils.format(" OR {} = {} ", useColumnAlias, user.getUserId()));
                } else {
                    // 数据权限为仅本人且没有userAlias别名不查询任何数据
                    sqlString.append(" OR 1=0 ");
                }
            }
        }

        if (StringUtils.isNotBlank(sqlString.toString())) {
            Object params = joinPoint.getArgs()[0];
            if (StringUtils.isNotNull(params) && params instanceof BaseEntity) {
                BaseEntity baseEntity = (BaseEntity) params;
                baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
                //将完成好的sql语句放在实体类 params的 dataScope属性中 这个属性是一个Map
            }
        }
    }

    /**
     * 拼接权限sql前先清空params.dataScope参数防止注入
     */
    private void clearDataScope(final JoinPoint joinPoint) {
        Object params = joinPoint.getArgs()[0];
        if (StringUtils.isNotNull(params) && params instanceof BaseEntity) {
            BaseEntity baseEntity = (BaseEntity) params;
            baseEntity.getParams().put(DATA_SCOPE, "");
        }
    }
}
